package com.rede.didiok.user.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import cn.hutool.core.util.RandomUtil;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.enums.AuthUserGender;
import me.zhyd.oauth.model.AuthUser;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.rede.didiok.common.constant.conf.MessageConf;
import com.rede.didiok.common.constant.conf.SQLConf;
import com.rede.didiok.common.constant.conf.SysConf;
import com.rede.didiok.common.constant.global.Constants;
import com.rede.didiok.common.dto.admin.SystemConfigDto;
import com.rede.didiok.common.dto.file.FileDto;
import com.rede.didiok.common.enums.*;
import com.rede.didiok.common.exception.exceptionType.InsertException;
import com.rede.didiok.common.exception.exceptionType.QueryException;
import com.rede.didiok.common.feign.AdminFeignClient;
import com.rede.didiok.common.holder.RequestHolder;
import com.rede.didiok.common.utils.JsonUtils;
import com.rede.didiok.common.utils.MD5Utils;
import com.rede.didiok.common.utils.StringUtils;
import com.rede.didiok.common.utils.business.WebUtil;
import com.rede.didiok.user.entity.UserAccountEntity;
import com.rede.didiok.user.entity.UserEntity;
import com.rede.didiok.common.feign.FileFeignClient;
import com.rede.didiok.user.service.AuthUserLoginService;
import com.rede.didiok.user.service.UserAccountService;
import com.rede.didiok.user.service.UserService;
import com.rede.didiok.common.utils.admin.SystemConfigUtil;


/**
 * 用户登录模块
 *
 * @author 遇见
 */
@Slf4j
@Service("authUserLoginService")
public class AuthUserLoginServiceImpl implements AuthUserLoginService {

    @Resource
    private WebUtil webUtil;
    @Resource
    private SystemConfigUtil systemConfigUtil;
    @Resource
    private FileFeignClient fileFeignClient;

    @Resource
    private AdminFeignClient adminFeignClient;
    /**
     * 用户模块
     */
    @Resource
    UserService userService;
    /**
     * 第三方用户与系统用户绑定模块
     */
    @Resource
    UserAccountService userAccountService;

    @Value(value = "${DEFAULE_PWD}")
    private String DEFAULE_PWD;

    /***************************** admin:start **************************/
    // region  didiok-admin

    // endregion
    /***************************** admin:end **************************/



    /***************************** web:start **************************/
    // region didiok-web

    @Override
    public UserEntity login(String source, AuthUser authUser, Integer registerMode, String unionid) {
        UserEntity user;
        Boolean exist = true;
        UserAccountEntity userAccount = userAccountService.queryRelation(source, authUser.getUuid());

        /**
         *
         * 当未查找到关系表，说明用户是第一次登录，需要创建一个用户
         */
        if (userAccount == null) {
            user = new UserEntity();
            exist = false;
            // 判断邮箱是否存在
            if (authUser.getEmail() != null) {
                String email = authUser.getEmail();
                user.setEmail(email);
            }
            // 判断用户性别
            if (authUser.getGender() != null) {
                AuthUserGender gender = authUser.getGender();
                if (SysConf.MALE.equals(gender.name())) {
                    user.setGender(Integer.valueOf(GenderEnum.MALE));
                } else if (SysConf.FEMALE.equals(gender.name())) {
                    user.setGender(Integer.valueOf(GenderEnum.FEMALE));
                } else {
                    user.setGender(Integer.valueOf(GenderEnum.UNKNOWN));
                }
            }
            // 设置新创建的用户
            user.setIsNewUser(Constants.NUM_ONE);
            // 新用户设置注册模式：1:正常情况下注册 2:小程序提交审核期间注册
            if(null != registerMode) {
                // 对于registerMode为2的数据不能轻易删除，因为小程序会保留登录数据，而且后端也不会判定为token失效，所以不会自动退出登录，如果使用已删除的登录数据继续操作，可能会引发报错
                user.setRegisterMode(registerMode);
            }
            // 设置用户权限
            String defaultUserAuth = adminFeignClient.getSysParamsValueByKey(SysConf.SYS_DEFAULT_USER_AUTH);
            user.setAuthCodeList(defaultUserAuth);

        } else {
            user = userService.getById(userAccount.getCreateUserUid());
        }

        // 通过头像uid获取图片
        String pictureList = this.fileFeignClient.getPicture(user.getAvatar(), SysConf.FILE_SEGMENTATION);
        List<String> photoList = webUtil.getPicture(pictureList);
        Map<String, Object> picMap = (Map<String, Object>) JsonUtils.jsonToObject(pictureList, Map.class);

        // 判断该用户是否含有头像信息
        if (SysConf.SUCCESS.equals(picMap.get(SysConf.CODE)) && photoList.size() > 0) {
//            List<Map<String, Object>> picData = (List<Map<String, Object>>) picMap.get(SysConf.DATA);
//            String fileOldName = picData.get(0).get(SysConf.FILE_OLD_NAME).toString();
//            // 判断本地的图片是否和第三方登录的一样，如果不一样，那么更新
//            // 如果旧名称为blob表示是用户自定义的，代表用户在本网站使用了自定义头像，那么就再也不同步更新第三方平台的头像了
//            // 如果是微信/QQ登录，直接显示原头像
//            if (fileOldName.equals(authUser.getAvatar()) || SysConf.BLOB.equals(fileOldName) || ELoginType.WECHAT.getName().equals(source) || ELoginType.QQ.getName().equals(source)) {
//                user.setPhotoUrl(photoList.get(0));
//            } else {
//                updateUserPhoto(authUser, user);
//            }

            // 有图片，就不更新了
            user.setPhotoUrl(photoList.get(0));
        } else {
            // 当获取头像失败时，需要从网站上进行获取
            updateUserPhoto(authUser, user);
        }

        // 如果还是没有头像，那么从默认头像库中获取
        if (StringUtils.isEmpty(user.getAvatar())) {
            //TODO 默认头像这里有待于研究
            String defaultAvatarStr = adminFeignClient.getSysParamsValueByKey(SysConf.USER_DEFAULT_AVATAR);
            List<String> defaultAvatarList = StringUtils.changeStringToString(defaultAvatarStr, Constants.SYMBOL_COMMA);
            // 随机一个头像
            if (defaultAvatarList.size() > 1) {
                Integer index = RandomUtil.randomInt(defaultAvatarList.size() - 1);
                user.setAvatar(defaultAvatarList.get(index));
                // 获取图片信息
                String defaultPictureList = this.fileFeignClient.getPicture(user.getAvatar(), SysConf.FILE_SEGMENTATION);
                List<String> defaultPhotoList = webUtil.getPicture(defaultPictureList);
                if (defaultPhotoList.size() > 0) {
                    user.setPhotoUrl(defaultPhotoList.get(0));
                }
            }
        }

        // 判断是否需要更换用户昵称
        if (StringUtils.isNotEmpty(authUser.getNickname()) && !exist) {
            user.setNickname(authUser.getNickname());
        }

        if (StringUtils.isNotEmpty(authUser.getRemark()) && !exist) {
            user.setSummary(authUser.getRemark());
        }

        if (user.getLoginCount() == null) {
            user.setLoginCount(1);
        } else {
            user.setLoginCount(user.getLoginCount() + 1);
        }

        // 获取浏览器，IP来源，以及操作系统
        user = userService.serRequestInfo(user);
        // 暂时将token也存入到user表中，为了以后方便更新redis中的内容
        if (authUser.getToken() != null && authUser.getToken().getAccessToken() != null) {
            user.setValidCode(authUser.getToken().getAccessToken());
        }

        // 用户等级换算
        UserLevelEnum userLevel = UserLevelEnum.getLvByExpValue(user.getExpValue());
        user.setUserLevel(userLevel.getLevel());

        if (exist) {
            user.updateById();
            // userAccount.getUnionid()为空，但是入参的 unionid 不为空，则修改 userAccount 的 unionid
            if(userAccount != null && StringUtils.isEmpty(userAccount.getUnionid())
                    && StringUtils.isNotEmpty(unionid)){
                userAccount.setUnionid(unionid);
                userAccount.updateById();
            }
        } else {
            user.setSocialUid(authUser.getUuid());
            user.setSource(authUser.getSource());
            user.setUserName(authUser.getUsername());
            // 如果昵称为空，那么直接设置用户名
            if (StringUtils.isEmpty(user.getNickname())) {
                user.setNickname(authUser.getUsername());
            }
            // 默认密码
            user.setPassword(MD5Utils.string2MD5(DEFAULE_PWD));
            // 设置是否开启评论邮件通知
            if (StringUtils.isNotEmpty(user.getEmail())) {
                // 有邮箱默认开启
                user.setStartEmailNotification(OpenStatusEnum.OPEN_STATUS);
            } else {
                user.setStartEmailNotification(OpenStatusEnum.CLOSE_STATUS);
            }
            // 增加新用户
            user.insert();

            //创建新的账号关联关系
            UserAccountEntity newRelation = new UserAccountEntity();
            newRelation.setCreateUserUid(user.getUid());
            newRelation.setCreateUserName(authUser.getUsername());
            newRelation.setNickname(authUser.getNickname());
            newRelation.setSource(authUser.getSource());
            newRelation.setSocialUid(authUser.getUuid());
            newRelation.setBindTime(new Date());
            newRelation.setGender(user.getGender());
            newRelation.setSummary(user.getSummary());
            newRelation.setAvatar(user.getAvatar());
            newRelation.setEmail(user.getEmail());
            // unionid
            if (StringUtils.isNotEmpty(unionid)) {
                newRelation.setUnionid(unionid);
            }
            newRelation.insert();
        }
        return user;
    }

    @Override
    public UserEntity bind(String source, AuthUser authUser, String userUid) {
        HttpServletResponse response = RequestHolder.getResponse();
        if (StringUtils.isEmpty(userUid)) {
            throw new InsertException("未查询到userUid，无法完成账号绑定");
        }
        UserEntity user = userService.getById(userUid);
        if (user == null) {
            throw new InsertException("未查询到登录用户，无法完成账号绑定");
        }

        // 通过头像uid获取图片
        String pictureList = this.fileFeignClient.getPicture(user.getAvatar(), SysConf.FILE_SEGMENTATION);
        List<String> photoList = webUtil.getPicture(pictureList);
        Map<String, Object> picMap = (Map<String, Object>) JsonUtils.jsonToObject(pictureList, Map.class);
        // 判断该用户是否含有头像信息
        if (SysConf.SUCCESS.equals(picMap.get(SysConf.CODE)) && photoList.size() > 0) {
            user.setPhotoUrl(photoList.get(0));
        }

        UserAccountEntity userAccount = userAccountService.queryRelation(source, authUser.getUuid());
        /**
         *
         * 当未查找到关系表，如果存在记录，说明账号已被绑定
         */
        if (userAccount == null) {
            //创建新的账号关联关系
            UserAccountEntity newRelation = new UserAccountEntity();
            newRelation.setCreateUserUid(user.getUid());
            newRelation.setCreateUserName(authUser.getUsername());
            newRelation.setNickname(authUser.getNickname());
            newRelation.setSource(authUser.getSource());
            newRelation.setBindTime(new Date());
            newRelation.setSocialUid(authUser.getUuid());
            // 判断邮箱是否存在
            if (authUser.getEmail() != null) {
                String email = authUser.getEmail();
                newRelation.setEmail(email);
            }
            // 判断用户性别
            if (authUser.getGender() != null) {
                AuthUserGender gender = authUser.getGender();
                if (SysConf.MALE.equals(gender.name())) {
                    newRelation.setGender(Integer.valueOf(GenderEnum.MALE));
                } else if (SysConf.FEMALE.equals(gender.name())) {
                    newRelation.setGender(Integer.valueOf(GenderEnum.FEMALE));
                } else {
                    newRelation.setGender(Integer.valueOf(GenderEnum.UNKNOWN));
                }
            }
            // 判断是否需要更换用户昵称
            if (StringUtils.isNotEmpty(authUser.getNickname())) {
                newRelation.setNickname(authUser.getNickname());
            }
            // 更新简介
            if (StringUtils.isNotEmpty(authUser.getRemark())) {
                newRelation.setSummary(authUser.getRemark());
            }
            // 更新用户头像
            updateUserPhoto(authUser, user);
            newRelation.setAvatar(user.getAvatar());
            newRelation.insert();
        } else {

            // 如果当前账户绑定的就是当前用户，那么提示已经绑定
            if (userUid.equals(userAccount.getCreateUserUid())) {
                throw new InsertException(MessageConf.USER_ACCOUNT_REPETITION);
            }
            // 只有当前用户的经验值低于100的时候，说明是一个新号才允许被覆盖，否则报错提示
            UserEntity oldUser = userService.getById(userAccount.getCreateUserUid());
            if (oldUser.getExpValue() > 100) {
                throw new InsertException(MessageConf.USER_ACCOUNT_EXIST);
            }
            userAccount.setCreateUserUid(userUid);
            userAccount.updateById();
        }

        // 用户等级换算
        UserLevelEnum userLevel = UserLevelEnum.getLvByExpValue(user.getExpValue());
        user.setUserLevel(userLevel.getLevel());
        return user;
    }

    @Override
    public List<UserAccountEntity> getUserAccountList() {
        String userUid = RequestHolder.getUserUid();
        if (StringUtils.isEmpty(userUid)) {
            throw new QueryException(Constants.USER_UID_EMPTY);
        }
        QueryWrapper<UserAccountEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(SQLConf.CREATE_USER_UID, userUid);
        queryWrapper.eq(SQLConf.STATUS, StatusEnum.ENABLE);
        List<UserAccountEntity> userAccountList = userAccountService.list(queryWrapper);
        // 对账号来源进行转化
        for (UserAccountEntity userAccount : userAccountList) {
            LoginTypeEnum loginType = LoginTypeEnum.getLoginTypeByName(userAccount.getSource());
            if (loginType == null) {
                continue;
            }
            userAccount.setSourceDesc(loginType.getDesc());
        }
        return userAccountList;
    }

    @Override
    public UserEntity getUserByOpenID(String openID) {
        if (StringUtils.isEmpty(openID)) {
            throw new QueryException("参数异常，openID is null");
        }
        QueryWrapper<UserAccountEntity> userAccountQueryWrapper = new QueryWrapper<>();
        userAccountQueryWrapper.eq(SQLConf.ACCOUNT_ID, openID);
        userAccountQueryWrapper.eq(SQLConf.STATUS, StatusEnum.ENABLE);
        userAccountQueryWrapper.last(SysConf.LIMIT_ONE);
        UserAccountEntity userAccount = userAccountService.getOne(userAccountQueryWrapper);
        if (userAccount == null) {
            throw new QueryException("用户未注册");
        }
        return userService.getById(userAccount.getCreateUserUid());
    }


    // endregion
    /***************************** web:end **************************/

    /**
     * 更新用户头像
     *
     * @param data
     * @param user
     */
    private void updateUserPhoto(AuthUser data, UserEntity user) {
        SystemConfigDto systemConfig = systemConfigUtil.getSystemConfig();

        // 获取到头像，然后上传到自己服务器
        FileDto fileDto = new FileDto();
        fileDto.setAdminUid(SysConf.DEFAULT_UID);
        fileDto.setCreateUserUid(SysConf.DEFAULT_UID);
        fileDto.setProjectName(SysConf.RANK_MEMBER);
        fileDto.setSortName(SysConf.USER);
        fileDto.setSystemConfig(JsonUtils.object2Map(systemConfig));
        List<String> urlList = new ArrayList<>();
        if (data.getAvatar() != null) {
            urlList.add(data.getAvatar());
        }
        fileDto.setUrlList(urlList);
        String res = this.fileFeignClient.uploadPicsByUrl(fileDto);
        Map<String, Object> resultMap = JsonUtils.jsonToMap(res);
        if (resultMap.get(SysConf.CODE) != null && SysConf.SUCCESS.equals(resultMap.get(SysConf.CODE).toString())) {
            if (resultMap.get(SysConf.DATA) != null) {
                List<Map<String, Object>> listMap = (List<Map<String, Object>>) resultMap.get(SysConf.DATA);
                if (listMap != null && listMap.size() > 0) {
                    Map<String, Object> pictureMap = listMap.get(0);

                    String localPictureBaseUrl = systemConfig.getLocalPictureBaseUrl();
                    String qiNiuPictureBaseUrl = systemConfig.getQiNiuPictureBaseUrl();
                    String picturePriority = systemConfig.getPicturePriority();
                    user.setAvatar(pictureMap.get(SysConf.UID).toString());
                    // 判断图片优先展示
                    if (OpenStatusEnum.OPEN.equals(picturePriority)) {
                        // 使用七牛云
                        if (pictureMap.get(SysConf.QI_NIU_URL) != null && pictureMap.get(SysConf.UID) != null) {
                            user.setPhotoUrl(qiNiuPictureBaseUrl + pictureMap.get(SysConf.QI_NIU_URL).toString());
                        }
                    } else {
                        // 使用自建图片服务器
                        if (pictureMap.get(SysConf.PIC_URL) != null && pictureMap.get(SysConf.UID) != null) {
                            user.setPhotoUrl(localPictureBaseUrl + pictureMap.get(SysConf.PIC_URL).toString());
                        }
                    }
                }
            }
        }
    }

}
